package ru.batrdmi.powermouse;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Comparing;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;

public class SettingsUI implements Configurable {
    private JComponent panel;
    private ComboBox comboBox;

    @Nls
    @Override
    public String getDisplayName() {
        return "PowerMouse";
    }

    @Nullable
    @Override
    public String getHelpTopic() {
        return null;
    }

    @Nullable
    @Override
    public JComponent createComponent() {
        panel = new JPanel(new GridBagLayout());
        panel.add(new JLabel("Action to execute on left+right mouse click: "));
        panel.add(comboBox = new ComboBox(getAllActions()));
        GridBagConstraints c = new GridBagConstraints();
        c.weightx = 1;
        panel.add(new JPanel(), c);
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 3;
        c.weighty = 1;
        panel.add(new JPanel(), c);
        return panel;
    }

    @Override
    public boolean isModified() {
        Action action = (Action) comboBox.getSelectedItem();
        return action != null
                && !Comparing.equal(EventDispatcher.getSettings().actionIdToExecuteOnPowerClick, action.id);
    }

    @Override
    public void apply() throws ConfigurationException {
        Action action = (Action) comboBox.getSelectedItem();
        if (action != null) {
            EventDispatcher.getSettings().actionIdToExecuteOnPowerClick = action.id;
        }
    }

    @Override
    public void reset() {
        String actionId = EventDispatcher.getSettings().actionIdToExecuteOnPowerClick;
        for (int i = 0; i < comboBox.getItemCount(); i++) {
            Action item = (Action) comboBox.getItemAt(i);
            if (Comparing.equal(actionId, item.id)) {
                comboBox.setSelectedItem(item);
                return;
            }
        }
    }

    @Override
    public void disposeUIResources() {
        panel = null;
        comboBox = null;
    }

    private Object[] getAllActions() {
        ActionManagerEx actionManager = ActionManagerEx.getInstanceEx();
        String[] actionIds = actionManager.getActionIds("");
        java.util.List<Action> actions = new ArrayList<Action>(actionIds.length + 1);
        actions.add(new Action(null, null));
        for (String actionId : actionIds) {
            AnAction action = actionManager.getAction(actionId);
            if (action == null) {
                continue;
            }
            String description = action.getTemplatePresentation().getText();
            if (description == null || description.isEmpty()) {
                continue;
            }
            actions.add(new Action(actionId, description));
        }
        Collections.sort(actions);
        return actions.toArray();
    }

    private static class Action implements Comparable<Action> {
        private final String id;
        private final String description;

        private Action(String id, String description) {
            this.id = id;
            this.description = description;
        }

        @Override
        public String toString() {
            return description == null ? "No action" : description;
        }

        @Override
        public boolean equals(Object o) {
            return o instanceof Action && Comparing.equal(description, ((Action) o).description);
        }

        @Override
        public int compareTo(@NotNull Action o) {
            if (description == null) {
                return o.description == null ? 0 : -1;
            }
            if (o.description == null) {
                return 1;
            }
            return description.compareTo(o.description);
        }
    }
}
